<?php
namespace App\Common\Model\Base\DataManager;

use App\Common as com;

/**
 * Class DataManager
 * @property $dataStore
 */
abstract class Main extends com\Cla\ClaBase {
	use com\Cla\ClaBase\Traits\GoPool;

	/**
	 * @var int|null
	 */
	private $_dataIdOrNull = null;

	//	protected $dataUnit = null;

	protected $paramDataIdOrWhere = null;

	protected $dataStore = null;

	/**
	 * DataUnit constructor.
	 * @param int|array|null $dataIdOrWhere [int]主数据id [array]主数据where [null]创建模式
	 * @param com\Cla\ClaBase\DataStore $dataStore
	 */
	public function __construct( $dataIdOrWhere = null, com\Cla\ClaBase\DataStore $dataStore = null ) {
		//
		$this->paramDataIdOrWhere = $dataIdOrWhere;
		//
		if( is_array( $dataIdOrWhere ) ){
			$this->setWhereOfUnique( $dataIdOrWhere );
		}else if( is_numeric( $dataIdOrWhere ) ){
			$this->_dataIdOrNull = $dataIdOrWhere;
			$this->goDataUnit()->setDataId( $dataIdOrWhere );
		}else if( $dataIdOrWhere !== null ){
			throw com\Lib\Err\Exception::makeOfNew( '参数类型错误', com\Lib\Err\Code::$sysFunParamError );
		}
		//
		$this->dataStore = $dataStore ?? com\Cla\ClaBase\DataStore::newOfThis( $this );
		$this->dataStore->setNxOfMain( $this );
		//
		parent::__construct();
	}


	/**
	 * @return com\Model\Base\DataUnit
	 */
	abstract protected function getDataUnit();

	private function setWhereOfUnique( array $where ):self {
		$this->goDataUnit()->goModelQuery()->where( $where );
		//
		return $this;
	}

	/**
	 * 是否为创建数据模式
	 * @return bool
	 */
	public function isCreate(  ):bool {
		return empty( $this->goDataUnit()->goModelQuery()->getQuery()->wheres );
	}

	/**
	 * 获取主键id->主数据id
	 * @return int
	 */
	public function getInitDataId(  ):int {
		$dataId = $this->getInitDataIdOrNull();
		if( $dataId === null ){
			throw com\Lib\Err\Exception::makeOfNew( 'dataId 不存在', com\Lib\Err\Code::$sysDataError );
		}
		return $dataId;
	}

	/**
	 * 获取主键id->主数据id 或 null
	 * @return int|null
	 */
	public function getInitDataIdOrNull(  ):?int {
		if( $this->_dataIdOrNull === null && ! $this->isCreate() ){
			$this->setInitDataId( $this->goDataUnit()->isExistToIDOrFail() );
		}
		//
		return $this->_dataIdOrNull;
	}

	/**
	 * 设置主键id->主数据id
	 * @param int $initMainDataId
	 * @return $this
	 */
	public function setInitDataId( int $initMainDataId ):self {
		$this->_dataIdOrNull = $initMainDataId;
		return $this;
	}

	/**
	 * @return com\Model\Base\DataUnit
	 */
	public function goDataUnit(  ):com\Model\Base\DataUnit {
		return $this->goPool( 'goDataUnit', function(){
			return $this->getDataUnit();
		} );
	}

	/**
	 * 保存数据(返回数据id)
	 * @return int 返回数据id
	 * @throws
	 */
	public function saveReId(  ):int {
		return $this->save()->getInitDataId();
	}

	/**
	 * 保存数据
	 * @return $this 返回数据id
	 * @throws
	 */
	public function save(  ):self {
		\Hyperf\DbConnection\Db::beginTransaction();
		try {
			if( method_exists( $this, '_save' ) ){
				$dataId = $this->_save();
			}else{
				// 创建->主表数据
				$dataId = $this->saveOfSelf();
				//
				if( method_exists( $this, '_saveOfSub' ) ){
					// 创建部分
					$this->_saveOfSub( $dataId );
				}
			}
			//
			\Hyperf\DbConnection\Db::commit();
			//
			$this->setInitDataId( $dataId );
		}catch( \Exception $e ){
			\Hyperf\DbConnection\Db::rollBack();
			return com\Lib\Err\Exception\Try_::dealWithException( $e, true );
		}finally{
			// 重置数据
			$this->goDataUnit()->goDataset()->reset();
		}
		//
		return $this;
	}

	//	abstract protected function _saveOfSub( int $dataId );

	/**
	 * 保存自身
	 * @return int
	 */
	protected function saveOfSelf(  ):int {
		// 检查
		if( $this->isCreate() ){
			$saveRes = $this->goDataUnit()->saveOfCreate( [], false );
		}else{
			$this->goDataUnit()->goWhereDy()->id( $this->getInitDataId() );
			$saveRes = $this->goDataUnit()->saveOfUpdate( [], false );
		}
		// 保存
		return $this->isCreate() ? $saveRes->getDataId() : $this->getInitDataId();
	}

	/**
	 * 删除全部关联数据
	 * @return bool [true][必返]
	 * @throws
	 */
	public function deleteTree(  ):bool {
		\Hyperf\DbConnection\Db::beginTransaction();
		try {
			//
			if( method_exists( $this, '_deleteTree' ) ){
				$this->_deleteTree();
			}else{
				$this->deleteTreeOfParent();
				$this->deleteTreeOfDown( true );
			}
			//
			\Hyperf\DbConnection\Db::commit();
			return true;
		}catch( \Exception $e ){
			\Hyperf\DbConnection\Db::rollBack();
			return com\Lib\Err\Exception\Try_::dealWithException( $e, true );
		}
	}
	
	/**
	 * 删除上级级关联数据
	 * @param  bool $isDelCurrentTable 是否删除当前表 [false][默认]
	 * @return bool [true][必返]
	 * @throws
	 */
	public function deleteTreeOfParent( bool $isDelCurrentTable = false ):bool  {
		\Hyperf\DbConnection\Db::beginTransaction();
		try {
			//
			if( method_exists( $this, 'goParent' ) ){
				$this->goParent()->deleteTreeOfParent( true );
				//
				if( $isDelCurrentTable === true ){
					$this->goDataUnit()->delete();
				}
			}
			//
			\Hyperf\DbConnection\Db::commit();
			return true;
		}catch( \Exception $e ){
			\Hyperf\DbConnection\Db::rollBack();
			return com\Lib\Err\Exception\Try_::dealWithException( $e, true );
		}
	}

	/**
	 * 删除下级关联数据
	 * @param  bool $isDelCurrentTable 是否删除当前表 [false][默认]
	 * @return bool [true][必返]
	 * @throws
	 */
	public function deleteTreeOfDown( bool $isDelCurrentTable = false ):bool  {
		\Hyperf\DbConnection\Db::beginTransaction();
		try {
			if( $isDelCurrentTable === true ){
				$this->goDataUnit()->delete();
			}
			//
			if( method_exists( $this, '_deleteTreeOfDown' ) ){
				$this->_deleteTreeOfDown( true );
			}
			//
			\Hyperf\DbConnection\Db::commit();
			return true;
		}catch( \Exception $e ){
			\Hyperf\DbConnection\Db::rollBack();
			return com\Lib\Err\Exception\Try_::dealWithException( $e, true );
		}
	}

}
